package com.dzsoftware.dzsoftwaresdk;

import android.app.Activity;
import android.content.Context;
// android.support使用
//import android.support.annotation.Nullable;
// androidx使用
import androidx.annotation.Nullable;
import android.util.Log;

import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * 接入文档链接:https://developer.android.com/google/play/billing/billing_library_overview
 **/
public class GoogleIAP {
    public static GoogleIAP Instance = new GoogleIAP();

    public static void TestFun() {
        System.out.println("GoogleIAP::TestFun()");
    }

    /**
     * 内购实列
     **/
    BillingClient billingClient;
    /**
     * 消耗型内购ID列表
     **/
    List<SkuDetails> vecSkuDetails = new LinkedList<>();
    /**
     * 待发货列表
     **/
    List<Purchase> vecWaitConsumePurchase = new LinkedList<>();
    /**
     * 内购application activity
     **/
    Context parent;
    /**
     * true: 打印调试日志, false: 不打印日志
     **/
    boolean m_bIsDebug = false;

    /**
     * 初始化内购
     * con: 内购application activity
     * sku: 消耗型内购ID
     * isDebug: true: 打印调试日志, false: 不打印日志
     **/
    public void InitIAP(Context con, String[] sku, boolean isDebug) {
        parent = con;
        m_bIsDebug = isDebug;
        billingClient = BillingClient.newBuilder(con).setListener(new PurchasesUpdatedListener() {
            @Override
            public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> list) {
                if (m_bIsDebug) {
                    System.out.println("GoogleIAP::onPurchasesUpdated(): 购买返回结果:" + billingResult.getResponseCode());
                }
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                        && list != null) {
                    for (Purchase purchase : list) {
                        //// 如果是订阅调用handlePurchase
                        //handlePurchase(purchase);
                        // 如果是消耗调用ConsumePurchase
                        ConsumePurchase(purchase);
                        // 用户完成支付,订单信息在此处理
                        CallUnity("GoogleIAP", "JavaCallPaySuccess", purchase.getOrderId() + "\t" + purchase.getOriginalJson());
                    }
                } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
                    // Handle an error caused by a user cancelling the purchase flow.
                    if (m_bIsDebug) {
                        System.out.println("GoogleIAP::onPurchasesUpdated(): 用户取消内购");
                    }
                    CallUnity("GoogleIAP", "JavaCallPayCanceled", billingResult.getDebugMessage());
                } else {
                    // Handle any other error codes.
                    if (m_bIsDebug) {
                        System.out.println("GoogleIAP::onPurchasesUpdated(): 内购发生错误code=" + billingResult.getResponseCode());
                    }
                    CallUnity("GoogleIAP", "JavaCallPayFailed", billingResult.getDebugMessage());
                }
            }
        }).enablePendingPurchases().build();

        billingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (m_bIsDebug) {
                    System.out.println("GoogleIAP::onBillingSetupFinished(): code:"
                            + billingResult.getResponseCode() + " msg:" + billingResult.getDebugMessage());
                }
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    // 内购初始成功,可以在这里查询内购信息
                    List<String> skuList = Arrays.asList(sku);
                    SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
                    params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
                    billingClient.querySkuDetailsAsync(params.build(),
                            new SkuDetailsResponseListener() {
                                @Override
                                public void onSkuDetailsResponse(BillingResult billingResult,
                                                                 List<SkuDetails> skuDetailsList) {
                                    // 查询内购信息结果回调,在这里处理内购信息结果
                                    vecSkuDetails = skuDetailsList;
                                    if (m_bIsDebug) {
                                        System.out.println("GoogleIAP::onSkuDetailsResponse(): code:" + billingResult.getResponseCode() + " msg:" + billingResult.getDebugMessage());
                                    }
                                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
                                        for (SkuDetails skuDetails : skuDetailsList) {
                                            if (m_bIsDebug) {
                                                System.out.println("GoogleIAP::onSkuDetailsResponse(): "
                                                        + " originalJson:" + skuDetails.getOriginalJson()
                                                );
                                            }
                                        }
                                    }
                                }
                            });
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // 在这里可以尝试重新链接内购服务
                if (m_bIsDebug) {
                    System.out.println("GoogleIAP::onBillingServiceDisconnected()");
                }
            }
        });
    }

    void handlePurchase(Purchase purchase) {
        if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
            // Grant entitlement to the user.
            // Acknowledge the purchase if it hasn't already been acknowledged.
            if (!purchase.isAcknowledged()) {
                AcknowledgePurchaseParams acknowledgePurchaseParams =
                        AcknowledgePurchaseParams.newBuilder()
                                .setPurchaseToken(purchase.getPurchaseToken())
                                .build();
                billingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() {
                    @Override
                    public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
                        if (m_bIsDebug) {
                            System.out.println("GoogleIAP::onAcknowledgePurchaseResponse(): code:" + billingResult.getResponseCode() + " msg:" + billingResult.getDebugMessage());
                        }
                    }
                });
            }
        } else if (purchase.getPurchaseState() == Purchase.PurchaseState.PENDING) {
            // Here you can confirm to the user that they've started the pending
            // purchase, and to complete it, they should follow instructions that
            // are given to them. You can also choose to remind the user in the
            // future to complete the purchase if you detect that it is still
            // pending.
        }
    }

    /**
     * 发起购买
     **/
    void Pay(String strSKU) {
        if (m_bIsDebug) {
            System.out.println("GoogleIAP::Pay(): " + strSKU);
        }

        if (vecSkuDetails != null) {
            SkuDetails details = null;
            for (int i = 0; i < vecSkuDetails.size(); i++) {
                String strThemSKU = vecSkuDetails.get(i).getSku();
                if (strThemSKU.equals(strSKU)) {
                    details = vecSkuDetails.get(i);
                    break;
                }
            }
            BillingFlowParams flowParams = BillingFlowParams.newBuilder()
                    .setSkuDetails(details)
                    .build();
            BillingResult responseCode = billingClient.launchBillingFlow((Activity) parent, flowParams);
            if (m_bIsDebug) {
                System.out.println("GoogleIAP::Pay(): code:" + responseCode.getResponseCode() + " msg:" + responseCode.getDebugMessage());
            }
        }
    }

    /**
     * 查询未消耗订单
     **/
    void QueryPurchases() {
        Purchase.PurchasesResult purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP);
        if (m_bIsDebug) {
            System.out.println("GoogleIAP::QueryPurchases(): purchasesCode:"
                    + purchasesResult.getResponseCode()
                    + " code:" + purchasesResult.getBillingResult().getResponseCode()
                    + " msg:" + purchasesResult.getBillingResult().getDebugMessage());
        }
        if(purchasesResult.getPurchasesList()!=null) {
            for (Purchase purchase : purchasesResult.getPurchasesList()) {
                if (m_bIsDebug) {
                    System.out.println("GoogleIAP::QueryPurchases(): sku:" + purchase.getSku() + " state:" + purchase.getPurchaseState());
                }
                //// 如果是订阅调用handlePurchase
                //handlePurchase(purchase);
                // 如果是消耗调用ConsumePurchase
                ConsumePurchase(purchase);
            }
        }
    }

    /**
     * 消耗订单
     **/
    void ConsumePurchase(Purchase purchase) {
        ConsumeParams consumeParams =
                ConsumeParams.newBuilder()
                        .setPurchaseToken(purchase.getPurchaseToken())
                        .setDeveloperPayload(purchase.getDeveloperPayload())
                        .build();
        vecWaitConsumePurchase.add(purchase);
        billingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {
            @Override
            public void onConsumeResponse(BillingResult billingResult, String s) {
                if (m_bIsDebug) {
                    System.out.println("GoogleIAP::onConsumeResponse(): code:"
                            + billingResult.getResponseCode() + " msg:"
                            + billingResult.getDebugMessage());
                }

                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    System.out.println("GoogleIAP::onConsumeResponse(): 发货:" + s);
                    int i = 0;
                    for (i = 0; i < vecWaitConsumePurchase.size(); i++) {
                        if (vecWaitConsumePurchase.get(i).getPurchaseToken().equals(s)) {
                            if (m_bIsDebug) {
                                System.out.println("GoogleIAP::onConsumeResponse(): 发货:" + vecWaitConsumePurchase.get(i).getSku());
                            }
                            break;
                        }
                    }
                    CallUnity("GoogleIAP", "JavaCallConsumePurchase", vecWaitConsumePurchase.get(i).getSku());
                    vecWaitConsumePurchase.remove(i);
                }
            }
        });
    }

    /**
     * 调用Unity C#代码
     * strObjName: 脚本\对象名称
     * strFunName: 函数名称
     * strParam: 参数字符串
     **/
    void CallUnity(String strObjName, String strFunName, String strParam) {
        try {
            Class<?> unityPlayer = Class.forName("com.unity3d.player.UnityPlayer");
            Method method = unityPlayer.getMethod("UnitySendMessage", String.class, String.class, String.class);
            method.invoke(unityPlayer, strObjName, strFunName, strParam);
        } catch (IllegalAccessException e) {
            System.out.println("GoogleIAP::CallUnity(): illegal method not found");
        } catch (InvocationTargetException e) {
            System.out.println("GoogleIAP::CallUnity(): invoke method not found");
        } catch (NoSuchMethodException e) {
            System.out.println("GoogleIAP::CallUnity(): unitysendmessage method not found");
        } catch (ClassNotFoundException e) {
            System.out.println("GoogleIAP::CallUnity(): unityplayer class not found");
        }
    }
}
